package com.yfk.web.controller;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yfk.base.utils.FileHandlerUtils;
import com.yfk.web.entity.YFKVO;
import com.yfk.web.service.IYFKService;
import com.yfk.web.util.BIPUtil;
import com.yfk.web.util.HttpClientUtil;
import com.yfk.web.util.ResultDataUtil;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/yfkService")
public class YFKController {
    Logger logger = LoggerFactory.getLogger(YFKController.class);
    @Autowired
    private YFKVO yfkVO;
    @Autowired
    private IYFKService yFKService;

    @RequestMapping("/test")
    public String yfkTest() {
        return "服务启动 SUCCESS";
    }

    /**
     * 获取友费控AccessToken
     * @return
     * @throws Exception
     */
    @RequestMapping("/token")
    public String getToken(@RequestBody String param) throws Exception {
        logger.info("-------1.获取token");
        JSONObject requestParam = JSONObject.parseObject(param);
        checkTokenInterfaceParams(requestParam);
        String apiUrl = joinURL(yfkVO.getSuffixTokenURL());
        String appKey = requestParam.getString("appKey");
        String appSecret = requestParam.getString("appSecret");
        logger.info("-------请求地址:【"+apiUrl+"】,appKey【"+appKey+"】,appSecret:【"+appSecret+"】--");
        return BIPUtil.getAccessToken(apiUrl, appKey, appSecret);
    }

    /**
     * 获取友费控AccessToken
     * @return
     * @throws Exception
     */
    @RequestMapping("/tbYFKGet")
    public String toYFKGet(@RequestBody String param) throws Exception {
        String result = "";
        try{
            logger.info("-------1.获取token");
            JSONObject requestParam = JSONObject.parseObject(param);
            this.checkGetInterfaceParams(requestParam);
            String toKenURL = this.yfkVO.getBaseURL()+this.yfkVO.getSuffixTokenURL();
            String token = this.yFKService.getAccessToken(toKenURL,
                    requestParam.getString("appKey"), requestParam.getString("appSecret"));
            HashMap<String, Object> acctokenmap = new HashMap<>();
            acctokenmap.put("access_token", token);
            JSONObject data = requestParam.getJSONObject("data");
            data.forEach((s,o) -> {
                acctokenmap.put(s, o);
            });
            String bodyURL = requestParam.getString("ywURL");
            result = HttpClientUtil.doGet(bodyURL,null, acctokenmap);
        }catch (Exception e){
            logger.info("##########GET请求异常:"+e.getMessage());
            result = ResultDataUtil.error(e.getMessage());
        }
        return result;
    }

    /**
     * 附件下载并上传
     * @return
     * @throws Exception
     */
    @RequestMapping("/downLoadAndUpload")
    public String downloadToUpload(@RequestBody String param) throws Exception{
        String result = "";
        File file = null;
        try{
            logger.info("###进入下载文件请求,参数:【{}】",param);
            JSONObject requestParam = JSONObject.parseObject(param);
            this.checkdownloadToUploadParams(requestParam);
            String toKenURL = this.yfkVO.getBaseURL()+this.yfkVO.getSuffixTokenURL();
            String access_token = this.yFKService.getAccessToken(toKenURL,
                    requestParam.getString("appKey"), requestParam.getString("appSecret"));
            String downloadUrl = requestParam.getString("downloadUrl"); // 附件下载地址
            String ywURL = requestParam.getString("ywURL"); // 附件上传接口
            String fileName = requestParam.getString("downloadName"); // 附件上传接口
            String uploadUrl = ywURL+"&access_token="+access_token;
            logger.info("###准备进行将临时文件地址【{}】转化为file文件,文件名称【{}】",downloadUrl,fileName);
            file = FileHandlerUtils.downloadFileFromUrl(downloadUrl,fileName);
            result = FileHandlerUtils.uploadFile(file, uploadUrl);
            logger.info("###文件上传费控成功!");
            FileHandlerUtils.deleteDownloadFile(file.getAbsolutePath());

        } catch (Exception e) {
            if(file != null){
                FileHandlerUtils.deleteDownloadFile(file.getAbsolutePath());
            }
            result = ResultDataUtil.error(e.getMessage());
        }
        return result;
    }

    /**
     *  跳板服务器请求友费控 --post请求
     * @param param
     * @return
     * @throws Exception
     */
    @RequestMapping("/tbYFK")
    public String requestYFKService(@RequestBody String param) throws  Exception{
        String result = "";
        try{
            JSONObject requestParam = JSONObject.parseObject(param);
            this.checkGetInterfaceParams(requestParam);
            String toKenURL = this.yfkVO.getBaseURL()+this.yfkVO.getSuffixTokenURL();
            String token = this.yFKService.getAccessToken(toKenURL,
                    requestParam.getString("appKey"), requestParam.getString("appSecret"));
            HashMap<String, Object> acctokenmap = new HashMap<>();
            acctokenmap.put("access_token", token);
            Object bodyParam = requestParam.get("data");
            String bodyURL = requestParam.getString("ywURL");
            result = HttpClientUtil.doPost(bodyURL, null, acctokenmap, bodyParam);
            if (null == result || "".equals(result)) {
                throw new Exception("请求地址:["+bodyURL+"],query参数:["+acctokenmap.toString()+"],body参数:["+bodyParam.toString()+"],费控响应为空");
            }
        }catch (Exception e){
            logger.info("##########GET请求异常:"+e.getMessage());
            result = ResultDataUtil.error(e.getMessage());
        }
        return result;
    }

    /**
     * 获取友费控单据列表
     * @param map
     * @return
     * @throws Exception
     */
    @RequestMapping("/queryYFLBillList")
    public Object getYFKBillQuery(@RequestBody Map map) throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        String bodyParam = objectMapper.writeValueAsString(map.get("body"));
        String apiUrl = this.joinURL(yfkVO.getSuffixYFKQueryURL());
        Map queryParam = (Map)map.get("queryParam");
        return this.yFKService.queryYFKBillQuery(apiUrl, queryParam, bodyParam);
    }
    @RequestMapping("/queryYFLBillAttachList")
    public Object getYFKBillAttachList(@RequestBody Map map) throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        String bodyParam = objectMapper.writeValueAsString(map.get("body"));
        String apiUrl = this.joinURL(yfkVO.getSuffixYFKBillAttachList());
        Map queryParam = (Map)map.get("queryParam");
        return this.yFKService.queryYFKBillAttachList(apiUrl, queryParam, bodyParam);
    }


    @RequestMapping("/queryYFLPrintBillPDF")
    public Object getYFKPrintBillPDF(@RequestBody Map map) throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        String bodyParam = objectMapper.writeValueAsString(map.get("body"));
        String apiUrl = this.joinURL(yfkVO.getSuffixYFKPrintBillPDF());
        Map queryParam = (Map)map.get("queryParam");
        return this.yFKService.queryYFKPrintBillPDF(apiUrl, queryParam, bodyParam);
    }

    /**
     * 获取友费控附件转化为文件流
     * @param map
     * @return
     * @throws IOException
     */
    @RequestMapping("/downloadFileURLIO")
    public ResponseEntity<InputStreamResource> downloadFile(@RequestBody Map map) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            String s = objectMapper.writeValueAsString(map);
            logger.info("文件流下载请求信息:【"+s+"】");
        } catch (Exception e) {
            logger.error("###文件流下载异常，Map转化为String异常:" + map.toString());
        }
        Object attachmentPath = map.get("attachmentPath");
        Object attachmentType = map.get("attachmentType");
        Object att = map.get("attachmentName");
        String attname =  att+"."+ attachmentType;
        String attachmentName = attname.replaceAll("[<>:\"/\\\\|?*]", "_"); // 特殊字符转义

        // 打开到外部文件的连接
        URL url = new URL(attachmentPath.toString());
        InputStream inputStream = url.openStream();

        // 设置响应头信息
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.parseMediaType("application/ofd"));
        headers.setContentDispositionFormData("attachment", attachmentName);
        logger.info("文件下载正常");
        // 返回响应实体
        return ResponseEntity.ok()
                .headers(headers)
                .body(new InputStreamResource(inputStream));
    }

    /**
     * 请求地址拼接
     * @param joinURL
     * @return
     * @throws Exception
     */
    private String joinURL(String joinURL) throws Exception {
        return yfkVO.getBaseURL() + joinURL;
    }

    /**
     * 检查获取友费控token参数
     * @param json
     * @throws Exception
     */
    private void checkGetInterfaceParams(JSONObject json) throws Exception{
        StringBuilder error = new StringBuilder();
        if(null == json.getString("appKey") || "".equals(json.getString("appKey"))){
            error.append("appKey不能为空 ");
        }
        if(null == json.getString("appSecret") || "".equals(json.getString("appSecret"))){
            error.append("appSecret不能为空 ");
        }
        if(null == json.getString("ywURL") || "".equals(json.getString("ywURL"))){
            error.append("业务接口地址【ywURL】不能为空,格式参照费控-请求地址");
        }
        if(null == json.getString("data") || "".equals(json.getString("data"))){
            error.append("业务接口请求数据【data】不能为空,格式参照费控接口-body参数");
        }
        if (error.toString().length() > 0) {
            throw new Exception(error.toString());
        }

    }

    /**
     * 检查获取友费控token参数
     * @param json
     * @throws Exception
     */
    private void checkTokenInterfaceParams(JSONObject json) throws Exception{
        StringBuilder error = new StringBuilder();
        if(null == json.getString("appKey") || "".equals(json.getString("appKey"))){
            error.append("appKey不能为空 ");
        }
        if(null == json.getString("appSecret") || "".equals(json.getString("appSecret"))){
            error.append("appSecret不能为空 ");
        }
        if (error.toString().length() > 0) {
            throw new Exception(error.toString());
        }

    }

    /**
     * 检查文件下载并上传参数
     * @param json
     * @throws Exception
     */
    private void checkdownloadToUploadParams(JSONObject json) throws Exception{
        StringBuilder error = new StringBuilder();
        if(null == json.getString("appKey") || "".equals(json.getString("appKey"))){
            error.append("appKey不能为空 ");
        }
        if(null == json.getString("appSecret") || "".equals(json.getString("appSecret"))){
            error.append("appSecret不能为空 ");
        }
        if(null == json.getString("downloadName") || "".equals(json.getString("downloadName"))){
            error.append("文件名称downloadName 不允许为空");
        }
        if(null == json.getString("downloadUrl") || "".equals(json.getString("downloadUrl"))){
            error.append("文件下载地址downloadUrl 不允许为空");
        }
        if(null == json.getString("ywURL") || "".equals(json.getString("ywURL"))){
            error.append("文件上传地址ywURL 不允许为空");
        }
        if (error.toString().length() > 0) {
            throw new Exception(error.toString());
        }

    }

}
